一.异常概述
    /**
     * 什么是异常?
     *   异常指的是java程序在运行期间出现的问题
     */
    /**
     * 异常的设计思想:
     *   由于java是纯面向对象语言,因此java将程序中可能出现的问题都映射成了java类
     *    映射的java类最终形成了异常体系
     * 异常体系:
     *    Throwable
     *       Exception:java程序中出现的异常都是Exception类或着Exception的子类
     *       Error:程序中出现错误,例如:服务器宕机,内存溢出
     *             我们一般改代码或者修改硬件来解决
     */
二.异常的处理
  1.JVM默认处理方式
     参照图解
  2.throw关键字抛出异常
        /**
         * 手动处理异常
         *  我们可以通过throw关键字抛出一个异常对象
         *   格式:throw new 异常类的构造方法;
         *   注意事项:
         *      一旦执行 throw new 异常类的构造方法;语句,该语句下面的代码都不在执行
         *      throw new 异常类的构造方法下面不能有任何语句,因为永远执行不到
         *      throw后面抛出的异常类,只能是异常体系一员
         */
   3.throws关键字用来异常声明
        /**
         * throws关键字
         * 当方法中抛出异常对象,我们为了让调用者知晓这个方法可能有异常抛出
         * 需要在方法上通过throws关键字声明异常类
         * 格式:
         * 修饰符 返回值类型 方法名(形参列表) throws 异常类名1,异常类名2,..{
         *
         * }
         */
    4.编译时异常与运行时异常
      异常(Exception)类:
         运行时异常:RuntimeException类及RuntimeException类的子类
         编译时异常:非RuntimeException类及其 非RuntimeException类的子类
      运行时异常的特点:
        运行时异常可处理(throw,throws,try...catch)可不处理
        编译时异常如果代码中有异常(throw),那么需要处理(throws,try...catch)处理
      什么时候用运行时异常?
         如果程序中出现的问题无法在编译时期被检测,而需要在运行时期检测,那么我们就需要使用运行时异常
         例如:例如数组索引越界,数组在运行时期才会在堆内存开辟数组,此时才会去找索引,当索引超出边界时候才报错
      什么时候用编译时异常?
         如果程序中出现的问题可以在编译时期检测,那么我们可以考虑使用编译时异常
         例如:价格和数量一旦有负值,我们知道计算总价肯定出问题
    5.try..catch..finally
      a.try..catch处理单个异常
            /**
             * 手动处理异常
             *   格式
             *    try{//检测可能出现异常的代码
             *     //一般写可能出现异常的代码
             *    }catch(异常类型 变量名){//捕获异常对象
             *                         //catch中异常类型定义为try中可能出现的异常类型
             *        //处理异常的代码
             *    }
             *
             */
      b.try..catch处理多个异常
            /**
             * 手动处理异常
             *   格式
             *    try{//检测可能出现异常的代码
             *     //一般写可能出现异常的代码
             *
             *    }catch(异常类型1 变量名){//捕获异常对象
             *                         //catch中异常类型定义为try中可能出现的异常类型
             *        //处理异常的代码
             *    }catch(异常类型2 变量名){//不同的异常找对应的catch处理,相当于对症下药
             *
             *    }... 后面可以写多个catch块
             *
             */
       c.finally代码块
            /**
             * 第一种格式格式:
             *   try{
             *     //第一种可能:try中的代码没有抛出异常,那么会去执行finally中的语句,程序继续向下执行
             *     //第二种可能:try中的代码出现了异常,异常下面的代码不在执行(try中的),接着会去找对应catch处理这个异常,
             *                执行catch中的语句,执行完catch中语句,接着会去执行finally中的语句
             *                finally语句执行完之后,程序继续向下执行
             *   }catch(异常类型 变量名){
             *
             *   }...finally{//finall跟在最后一个catch的末尾
             *      //无论try中是否抛出异常,finally中的语句都会被执行
             *      //我们一般把资源释放语句放在finally中,防止资源无法释放,例如:IO流关闭,数据连接关闭..
             *   }
             *
             *第二种格式:
             *   try{
             *      //第一种可能:try中的代码没有抛出异常,那么会去执行finally中的语句,程序继续向下执行
             *      //第二种可能:try中的代码出现了异常,此时try下面的语句不再执行(try中),接着会去执行finally中的语句
             *                 执行完finally中的语句之后,JVM会去处理这个异常,采用默认处理方式,打印异常信息和异常追踪信息
             *                 最后停止程序
             *
             *   }finally{
             *     //无论try中是否抛出异常,finally中的语句都会被执行
             *   }
             *
             */
        d.try...catch注意事项
            /**
             * try...catch注意事项
             *  1.如果多个catch中的异常类型没有父子关系,那么多个catch的顺序不影响最终结果
             *  2.如果多个catch中的异常类型有父子关系,那么父类型的catch不能放在子类型的上面
             *    因为无论子类型异常对象,还是父类型的异常对象都会被父类型的catch捕获,那么在父类型catch下面的子类型catch将永远执行不到
             *   解决方案:
             *     将子类型的catch放在父类型的catch上方
             */
      6.异常在继承中的使用规则
        /*
         * 编译时异常在继承中的使用规则:
         *   1.如果父类中的方法声明一个异常,那么子类在重写该方法的时候,
         *      可以不声明该异常或者声明该异常或者声明该异常的子类
         *   2.如果父类中的方法声明多个异常,那么子类在重写该方法的时候,
         *      可以声明父类异常的子集(包含空集)
         *     {a,b} {a},{b},{a,b} 空集
         *   3.如果父类没有声明异常,子类在重写该方法时也不能声明异常
         * */
     7.异常体系的方法
        /**
         * Throwable中的方法:被所有的异常类继承,所以所有的异常对象都可以使用
         *  String getMessage()
         *           返回是异常对象中封装异常信息
         *  void printStackTrace()
         *          打印的是异常信息和异常追踪信息
         */
      8.自定义异常
        /**
         * 将AgeException继承Exception类或者RuntimeException类就可以成为异常体系的一员
         * 如果继承Exception代表这个自定义异常为编译时异常
         * 如果继承RuntimeException那么这个异常就是运行时异常
         * class 类名 extends Exception 或 RuntimeExpetion{
         *     public 类名(){
         *         super();
         *     }
         *     public 类名(String message){
         *         super(message);
         *
         *     }
         * }
         *
         */